﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


// This namespace has several classes, by creating a separate namespace we orginaize the classes under a namespace
namespace ClassesInCSharp
{

    class Shape
    {
        // Instance variables, each object has it's own instance variabeles
        string Contens;
        int Value;

        // Here we create a static variabele, this variable is used by all created objects and is only created once
        // Since the value of PI is always the same using a static variabele is the best choice
        // For example if we create ten objects the variable PI is only created once and shared by all objects
        static float Pi = 3.141F;

        // Static constructor to change the static variable PI
        // Static constructors are called before instance constructors
        // A Static constructor is called only once, nomatter how many objects are created
        static Shape()
        {
            Shape.Pi = 3.1412F;
        }

        // Default constructor
        public Shape()
        {
            Contens = "Default value";
            Value = 0;
        }

        // Constructor with parameters
        public Shape(string StringContens, int ValueContens){

            // This means the variabele of this instance
            // This can be left out but it increases the readability
            this.Contens = StringContens;
            this.Value = ValueContens;
        }

        // Destructor, cleans up the created instance
        ~Shape()
        {
            // Nothing special
        }

        // A member method, each object has it's own member method in the memory
        public void PrintValues()
        {
            Console.WriteLine("Contens: " + Contens  + " " +  "Value: " + Value);
        }

        // Static method, this method is created only once in the memory and is shared by all objects
        static void PrintPI()
        {
            Console.WriteLine("PI: " + Shape.Pi);
        }

    }

    class Program
    {
        // A simple method, it's static this means we can call it without it belonging to a class
        // Passing value of integer by copy by value, it makes a copy of the given value
        // At the end of the method the inital value did't change
        // To put it simpely we make a to seperate diffrent copy's one is the orginoal passed variable
        // and one is the internal value
        public static void SimpleMethod(int Value)
        {
            Value++;
        }

        // A simple method, it's static this means we can call it without it belonging to a class
        // Here we pass by reference, this means that we use the reference of the value given by the parameter
        // The results is that value that is changed in this method will be written directly in the memory address of variable that
        // has been given to to parameter. We reference it in the method
        // To put is simpely we there a two diffrent variables but they both point to the same memory address
        public static void SimpleMethod2(ref int Value)
        {
            Value++;
        }


        static void Main(string[] args)
        {
            // Create a Shape object with the default constructor
            Shape Shape1 = new Shape();

            // Create a Shape object with the parameter constructor
            Shape Shape2 = new Shape("Test", 10);

            // Use ? to make a nullable variabele, are usefull for example when a user don't fill in a form question
            // Like whats your age, if the user does not fill in the value this will be null (not 0).
            int? Number = null;

            // Normal non nullable variabele
            int Number2 = 0;

            // We can normaly add value to a nullabele value
            Number = 0;

            // Call method 
            SimpleMethod(Number2);

            //Number2 should still be 0
            Console.WriteLine("Number2: " + Number2);

            // Call method 
            SimpleMethod2(ref Number2);

            //Number2 should be 1
            Console.WriteLine("Number2: " + Number2);

            // Print values for both shapes
            Shape1.PrintValues();

            Shape2.PrintValues();

        }
    }
}
